import {
  Body,
  Controller,
  Del,
  Get,
  Inject,
  Post,
  Put,
  Query,
} from '@midwayjs/core';
import { ProcessFilesService } from '../../service/process_files/process_files.service';
import { Validate } from '@midwayjs/validate';
import {
  ListParamsValidator,
  StrIdsValidator,
  StrIdValidator,
} from '../../validator';
import {
  EditProcessFilesValidator,
  SaveProcessFilesValidator,
} from '../../validator/process_files/process_files';
import { FileService } from '../../service/file/file.service';
import { isNotEmpty } from '../../utils/isHelper';
import { generateRandomString } from '../../utils/toolsHelper';
import { Context } from '@midwayjs/koa';
import { resolve } from 'path';
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
import dayjs = require('dayjs');
import { BadRequestError } from '@midwayjs/core/dist/error/http';
import { PDFDocument } from 'pdf-lib';
import { UserService } from '../../service/user/user.service';
import { ProcessFilesSchema } from '../../schema';

@Controller('/process_files', { tagName: '' })
export class ProcessFilesController {
  @Inject()
  process_filesService: ProcessFilesService;

  @Inject()
  fileService: FileService;

  @Inject()
  useService: UserService;

  @Inject()
  ctx: Context;

  @Post('/list', { summary: '列表' })
  @Validate()
  async list(@Body() body: ListParamsValidator<ProcessFilesSchema>) {
    const data = await this.process_filesService.list(body);
    return Object.assign(data, body);
  }

  @Post('/save', { summary: '保存' })
  @Validate()
  async save(@Body() body: SaveProcessFilesValidator) {
    return await this.process_filesService.save(body);
  }

  @Get('/info', { summary: '信息' })
  @Validate()
  async info(@Query() body: StrIdValidator) {
    return await this.process_filesService.info(body.id);
  }

  @Del('/remove', { summary: '删除' })
  @Validate()
  async remove(@Query() body: StrIdValidator) {
    return await this.process_filesService.remove(body.id);
  }

  @Del('/delete', { summary: '（真）删除' })
  @Validate()
  async realRemove(@Query() body: StrIdValidator) {
    return await this.process_filesService.realRemove(body.id);
  }

  @Put('/edit', { summary: '编辑' })
  @Validate()
  async edit(
    @Query() query: StrIdValidator,
    @Body() body: EditProcessFilesValidator
  ) {
    const process_files = await this.process_filesService.info(query.id);
    Object.assign(process_files, body);
    return await this.process_filesService.save(process_files);
  }

  @Post('/merge_pdf', { summary: '合并PDF文件' })
  @Validate()
  async mergePdf(@Body() body: StrIdsValidator) {
    const startTime = Date.now();
    const files = await this.fileService.findByIds(body.ids);

    console.log(files);

    const paths = files.map(file => file.fileUrl);

    const serverPath = this.ctx.getApp().getAppDir();
    const pdfFilesInMachine = paths.map(ele => resolve(serverPath, `./${ele}`));

    const pdfDoc = await PDFDocument.create();

    for (let i = 0; i < pdfFilesInMachine.length; i++) {
      const localPath = pdfFilesInMachine[i];
      const PDFItem = await PDFDocument.load(readFileSync(localPath));
      for (let j = 0; j < PDFItem.getPageCount(); j++) {
        const [PDFPageItem] = await pdfDoc.copyPages(PDFItem, [j]);
        // 获取当前页面的宽度和高度
        const { width, height } = PDFPageItem.getSize();
        //处理pdf尺寸
        PDFPageItem.scale(960 / width, 1280 / height);
        pdfDoc.addPage(PDFPageItem);
      }
    }
    const pdfBytes = await pdfDoc.save();
    const savePath = resolve(serverPath, './merge');
    if (!existsSync(savePath)) {
      mkdirSync(savePath);
    }
    const pdfPath = resolve(savePath, './pdf');
    if (!existsSync(pdfPath)) {
      mkdirSync(pdfPath);
    }
    const fileName = resolve(
      pdfPath,
      `${dayjs(new Date()).unix()}-${generateRandomString(12)}.pdf`
    );
    writeFileSync(fileName, pdfBytes);
    const endTime = Date.now();

    const reqCtx: any = this.ctx.requestContext.get('ctx');

    const user = await this.useService.info(reqCtx.header.uid);

    if (!isNotEmpty(user)) throw new BadRequestError('用户不存在');

    return await this.process_filesService.save({
      path: this.getFilePath(fileName),
      diffTime: `${endTime - startTime}ms`,
      user,
    });
  }

  private getFilePath(path: string) {
    const pathArr = path.split('merge');
    const [, url] = pathArr;
    return `/merge${url}`;
  }
}
